package com.hopes.bizz.risk.applet.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hopes.bizz.common.core.util.CollectionUtils;
import com.hopes.bizz.common.core.util.StringUtils;
import com.hopes.bizz.risk.applet.service.AppletMeasureTaskService;
import com.hopes.bizz.risk.common.constant.HidDicConstant;
import com.hopes.bizz.risk.common.constant.IntegralEventEnum;
import com.hopes.bizz.risk.common.constant.RiskDicConstant;
import com.hopes.bizz.risk.common.constant.enums.RiskHidSourceEnum;
import com.hopes.bizz.risk.common.constant.enums.RiskModDictEnum;
import com.hopes.bizz.risk.control.dto.RiskMeasureTaskRecordDTO;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskEntity;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskRecordEntity;
import com.hopes.bizz.risk.control.entity.RiskUnitEntity;
import com.hopes.bizz.risk.control.service.RiskMeasureTaskRecordService;
import com.hopes.bizz.risk.control.service.RiskMeasureTaskService;
import com.hopes.bizz.risk.control.service.RiskUnitService;
import com.hopes.bizz.risk.control.vo.RiskMeasureTaskRecordVO;
import com.hopes.bizz.risk.hid.dto.RiskHidHiddenDangerDTO;
import com.hopes.bizz.risk.hid.service.RiskHidHiddenDangerService;
import com.hopes.bizz.risk.integral.bo.IntegralEvent;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.common.data.tenant.TenantBroker;
import com.hopes.boss.common.security.service.BossUser;
import com.hopes.boss.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @Description 小程序 双重预防排查任务
 * @time 2023/7/28 13:10
 */
@Service
@RequiredArgsConstructor
public class AppletMeasureTaskServiceImpl implements AppletMeasureTaskService {

    private final RiskUnitService riskUnitService;
    private final RiskMeasureTaskService riskMeasureTaskService;
    private final RiskHidHiddenDangerService riskHidHiddenDangerService;
    private final RiskMeasureTaskRecordService riskMeasureTaskRecordService;

    private final ApplicationEventPublisher eventPublisher;

    /**
     * 分页查询隐患排查任务
     *
     * @param page              分页参数
     * @param measureTaskRecord 查询条件
     * @return 结果集
     */
    @Override
    public Page<RiskMeasureTaskRecordVO> selectPage(Page<RiskMeasureTaskRecordEntity> page, RiskMeasureTaskRecordVO measureTaskRecord) {
//        Assert.notNull(measureTaskRecord.getTaskStatus(), "任务状态不可为空！");
//        final BossUser user = SecurityUtils.getUser();
//        if (null == user || null == user.getId()) {
//            throw new BizException("获取当前用户失败！");
//        }
//        // 根据二维码code获取风险单元id
//        RiskUnitEntity riskUnit = riskUnitService.lambdaQuery().eq(RiskUnitEntity::getQrCode, measureTaskRecord.getRiskQrCode()).one();
//        String riskUnitId = null;
//        if (ObjectUtil.isNotNull(riskUnit)) {
//            riskUnitId = riskUnit.getId();
//        } else if (StringUtils.isNotBlank(measureTaskRecord.getRiskQrCode())) {
//            riskUnitId = measureTaskRecord.getRiskQrCode();
//        }
//        final LambdaQueryWrapper<RiskMeasureTaskRecordEntity> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.eq(RiskMeasureTaskRecordEntity::getTaskStatus, measureTaskRecord.getTaskStatus())
//                .eq(ObjectUtil.isNotNull(measureTaskRecord.getWorkType()), RiskMeasureTaskRecordEntity::getWorkType, measureTaskRecord.getWorkType())
//                .eq(ObjectUtil.isNotNull(riskUnitId), RiskMeasureTaskRecordEntity::getRiskUnitId, riskUnitId)
//                .like(StringUtils.isNotBlank(measureTaskRecord.getTaskName()), RiskMeasureTaskRecordEntity::getTaskName, measureTaskRecord.getTaskName())
//                .ge(ObjectUtil.isNotNull(measureTaskRecord.getTaskStartTime()), RiskMeasureTaskRecordEntity::getTaskStartTime, measureTaskRecord.getTaskStartTime())
//                .le(ObjectUtil.isNotNull(measureTaskRecord.getTaskDeadlineTime()), RiskMeasureTaskRecordEntity::getTaskDeadlineTime, measureTaskRecord.getTaskDeadlineTime());
//        if (!SecurityUtils.isAdmin()) {
//            queryWrapper.like(RiskMeasureTaskRecordEntity::getResponsibleUserIds, user.getId());
//        }
//        if (RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_FINISH.equals(measureTaskRecord.getTaskStatus())) {
//            queryWrapper.orderByDesc(RiskMeasureTaskRecordEntity::getTaskHandleTime);
//        } else {
//            queryWrapper.orderByDesc(RiskMeasureTaskRecordEntity::getCreateTime);
//        }
//        final Page<RiskMeasureTaskRecordEntity> pageInfo = riskMeasureTaskRecordService.page(page, queryWrapper);
//        final List<RiskMeasureTaskRecordVO> collect = pageInfo.getRecords().stream().map(item -> {
//            final RiskMeasureTaskRecordVO recordVO = new RiskMeasureTaskRecordVO();
//            BeanUtils.copyProperties(item, recordVO);
//            return recordVO;
//        }).collect(Collectors.toList());
//
//        final Page<RiskMeasureTaskRecordVO> res = new Page<>(page.getCurrent(), page.getSize(), pageInfo.getTotal());
//        res.setRecords(collect);
        return null;
    }

    @Override
    public RiskMeasureTaskRecordVO getById(Long id) {
        final RiskMeasureTaskRecordEntity measureTaskRecordEntity = riskMeasureTaskRecordService.getById(id);
        final RiskMeasureTaskRecordVO riskMeasureTaskRecordVO = new RiskMeasureTaskRecordVO();
        BeanUtils.copyProperties(measureTaskRecordEntity, riskMeasureTaskRecordVO);
        return riskMeasureTaskRecordVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSubmitTask(Long[] ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        final Long userId = Optional.ofNullable(SecurityUtils.getUser()).map(BossUser::getId).orElse(null);
        Assert.notNull(userId, "获取当前用户信息失败！");
        // 查询数据
        final List<RiskMeasureTaskRecordEntity> measureTaskRecordList = riskMeasureTaskRecordService
                .list(Wrappers.<RiskMeasureTaskRecordEntity>lambdaQuery().in(RiskMeasureTaskRecordEntity::getId, ids));

        final Date time = Calendar.getInstance().getTime();
        measureTaskRecordList.forEach(item -> {
            item.setTaskHandleTime(time);
            item.setTaskHandleUserId(userId);
            item.setCheckStatus(RiskDicConstant.HIDDEN_CHECK_STATUS_CONFORM);
            item.setTaskStatus(RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_FINISH);
        });
        final boolean b = riskMeasureTaskRecordService.updateBatchById(measureTaskRecordList);
        // 双体系排查任务
        for (RiskMeasureTaskRecordEntity entity : measureTaskRecordList) {
            // 统计积分
            TenantBroker.runAs(entity.getTenantId(), (id) -> {
                final IntegralEvent integralEvent = new IntegralEvent();
                integralEvent.setBusinessId(entity.getId());
                integralEvent.setModule(IntegralEventEnum.risk_control_integral);
                eventPublisher.publishEvent(integralEvent);
            });
        }
        return Boolean.TRUE;
    }

    /**
     * 提交隐患排查任务
     *
     * @param measureTaskRecordDTO 任务
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitTask(RiskMeasureTaskRecordDTO measureTaskRecordDTO) {
        Assert.notNull(measureTaskRecordDTO.getId(), "参数异常！");
        final Long userId = Optional.ofNullable(SecurityUtils.getUser()).map(BossUser::getId).orElse(null);
        Assert.notNull(userId, "获取当前用户信息失败！");


        final Calendar instance = Calendar.getInstance();

        final RiskMeasureTaskRecordEntity taskRecordEntity = new RiskMeasureTaskRecordEntity();
        BeanUtils.copyProperties(measureTaskRecordDTO, taskRecordEntity);
        taskRecordEntity.setId(measureTaskRecordDTO.getId());
        taskRecordEntity.setTaskHandleUserId(userId);
        taskRecordEntity.setTaskHandleTime(instance.getTime());
        taskRecordEntity.setRemarks(measureTaskRecordDTO.getHiddenDanger().getRemarks());
        taskRecordEntity.setTaskStatus(RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_FINISH);

        final boolean res = riskMeasureTaskRecordService.updateById(taskRecordEntity);
        if (res) {
            // 1、判断隐患排查是否符合
            if (measureTaskRecordDTO.getCheckStatus().equals(RiskDicConstant.HIDDEN_CHECK_STATUS_NOT_CONFORM)) {
                final RiskHidHiddenDangerDTO hiddenDanger = measureTaskRecordDTO.getHiddenDanger();
                // 2、查询隐患排查任务
                final RiskMeasureTaskRecordEntity measureTaskRecordEntity = riskMeasureTaskRecordService.getById(measureTaskRecordDTO.getId());
                // 3、封装隐患上报对象
                final RiskHidHiddenDangerDTO hidHiddenDangerDTO = new RiskHidHiddenDangerDTO();
                BeanUtils.copyProperties(hiddenDanger, hidHiddenDangerDTO);

                hidHiddenDangerDTO.setHidSource(HidDicConstant.HID_SOURCE_TWO_SYSTEM_TASK);
                hidHiddenDangerDTO.setReportUserId(userId);
                hidHiddenDangerDTO.setReportPhoto(Optional.ofNullable(hiddenDanger.getReportPhoto()).orElseGet(measureTaskRecordDTO::getPhoto));
                hidHiddenDangerDTO.setBizId(measureTaskRecordDTO.getId());
                hidHiddenDangerDTO.setBizName(RiskHidSourceEnum.RISK_CONTROL.getName());
                hidHiddenDangerDTO.setBizCode(RiskHidSourceEnum.RISK_CONTROL.getCode());
                hidHiddenDangerDTO.setCheckRecordId(measureTaskRecordDTO.getId());
                hidHiddenDangerDTO.setRiskUnitId(measureTaskRecordEntity.getRiskUnitId());
                hidHiddenDangerDTO.setRiskControlId(measureTaskRecordEntity.getRiskControlId());
                hidHiddenDangerDTO.setHazardCode(queryHazardCodeByRiskUnit(measureTaskRecordEntity.getRiskUnitId()));
                hidHiddenDangerDTO.setHidCategory(queryHidCategoryByTaskId(measureTaskRecordEntity.getRiskCheckConfigId()));

                // 隐患类别（其他隐患：0；主要负责人登记隐患：1；技术负责人登记隐患：2；操作负责人登记隐患：3）
                // 默认为其他隐患：0
                hidHiddenDangerDTO.setHidCategory(Optional.of(measureTaskRecordEntity).map(RiskMeasureTaskRecordEntity::getWorkType).orElse(BigDecimal.ZERO.intValue()));
            }
        }
        // 统计积分
        final RiskMeasureTaskRecordEntity taskRecord = riskMeasureTaskRecordService.getById(measureTaskRecordDTO.getId());
        Assert.notNull(taskRecord, "双体系排查任务获取失败！");
        TenantBroker.runAs(taskRecord.getTenantId(), (id) -> {
            final IntegralEvent integralEvent = new IntegralEvent();
            integralEvent.setBusinessId(measureTaskRecordDTO.getId());
            integralEvent.setModule(IntegralEventEnum.risk_control_integral);
            eventPublisher.publishEvent(integralEvent);
        });

        return true;
    }

    private Integer queryHidCategoryByTaskId(Long taskId) {
        if (Objects.isNull(taskId)) {
            return RiskDicConstant.RISK_WORK_TYPE_0;
        }
        final RiskMeasureTaskEntity riskMeasureTask = riskMeasureTaskService.getById(taskId);
        return Optional.ofNullable(riskMeasureTask).map(RiskMeasureTaskEntity::getWorkType).orElse(RiskDicConstant.RISK_WORK_TYPE_0);
    }


    private String queryHazardCodeByRiskUnit(Long riskUnitId) {
        if (Objects.isNull(riskUnitId)) {
            return null;
        }
        // 查询风险单元
        final RiskUnitEntity riskUnitEntity = riskUnitService.getById(riskUnitId);
        if (null == riskUnitEntity || null == riskUnitEntity.getRiskObjectId()) {
            return null;
        }
        final List<SysDictItem> riskObjectList = DictResolver.getItemsByType(RiskModDictEnum.risk_object);
        final Map<String, SysDictItem> labelValueMap = riskObjectList.stream().filter(e -> null != e.getCode()).collect(Collectors.toMap(SysDictItem::getCode, e -> e));
        if (!labelValueMap.containsKey(riskUnitEntity.getRiskObjectId().toString())) {
            return null;
        }
        return labelValueMap.get(riskUnitEntity.getRiskObjectId().toString()).getExt1();
    }
}
